#ifndef _SPIFFS_H
#define _SPIFFS_H

#include <stdio.h>
#include <dirent.h>
#include "freertos/FreeRTOS.h"
#include "nvs_flash.h"
#include "esp_spiffs.h"
#include <string>

#ifdef __cplusplus
extern "C"
{
    class SPI_FFS
    {

    public:
        static SPI_FFS &getInstance();

        /**
         * Initializes the SPIFFS file system
         *
         * @param mount_point The mount point for the SPIFFS file system. Defaults to "/storage" if not specified.
         * @param partition_label_name The name of the partition to be used for the SPIFFS file system. Defaults to "storage" if not specified.
         * @param max_open_file_number The maximum number of files that can be opened simultaneously. Defaults to 5 if not specified.
         */
        void begin(const std::string &mount_point = "/storage", const std::string &partition_label_name = "storage", uint8_t max_open_file_number = 5);

        /**
         * Closes a file
         *
         * @param file The file pointer to be closed
         */
        void closeFile(FILE *file);

        /**
         * Closes a file and deinitializes the SPIFFS file system
         *
         * @param file The file pointer to be closed
         */
        void closeFileAndSpiffsAll(FILE *file);

        /**
         * Opens a file in the SPIFFS file system
         *
         * @param path The path to the file to be opened
         * @param open_type The type of open operation, such as "r" for reading, "w" for writing, "a" for appending, etc.
         * @return A file pointer to the opened file, or NULL if the file could not be opened
         */
        FILE *open(std::string path, std::string open_type);

        /**
         * Reads the contents of a file
         *
         * @param file The file pointer to the file to be read
         * @return A string containing the contents of the file
         */
        std::string read(FILE *file);
        std::string read(FILE *file, size_t size);
        std::string read(const std::string &path);

        void readToBuffer(FILE *file, void *buffer, size_t size);

        /**
         * Writes a string to a file
         *
         * @param file The file pointer to the file to be written to
         * @param str The string to be written to the file
         * @return An esp_err_t value indicating the success or failure of the write operation
         */
        esp_err_t write(FILE *file, const std::string &str);
        esp_err_t write(FILE *file, const char *data);

        esp_err_t remove(const std::string &path);
        esp_err_t rename(const std::string &old_path, const std::string &new_path);

        size_t getSize(FILE *file);

        DIR *openDir(const std::string &path);
        uint16_t getDirFileCount(const std::string &dir_name);

        /**
         * Overloads the not operator to check if the SPIFFS file system is initialized
         *
         * @return true if the SPIFFS file system is not initialized, false otherwise
         */
        bool operator!();

    private:
        esp_err_t build_system_success;
        bool sucess_begin = false;
        std::string mount_point = "/storage";
        /**
         * Constructor for the SPI_FFS class, which initializes the maximum number of open files
         *

         */
        SPI_FFS();
    };

    extern SPI_FFS &SPIFFS;
}
#endif

#endif
